﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using KegData;

namespace KegCommunication
{
    public enum KegBotStatus
    {
        Stopped,
        Running,
        Error,
        ErrorPacketFormat,
        ErrorTimeOut,
        ErrorConnection,
        ErrorPing,
    }

    // A delegate type for hooking up change notifications.
    public delegate void PacketEventHandler(object sender, PacketEventArgs e);
    public delegate void PourEventHandler(object sender, PourEventArgs e);
    public delegate void TemperatureEventHandler(object sender, TemperatureEventArgs e);
    public delegate void StatusEventHandler(object sender, StatusEventArgs e);
    public delegate void HelloEventHandler(object sender, HelloEventArgs e);
    public delegate void UserAuthenticatedHandler(object sender, UserAuthenticatedEventArgs e);

    // Specific callbacks for plugins
    public delegate void PourPluginEventHandler(Pour p);
    public delegate void TemperaturePluginEventHandler(Temperature t);

    [Serializable()]
    public class HelloEventArgs : EventArgs, ISerializable
    {
        private readonly uint _version;

        public HelloEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this._version = (uint)info.GetValue("Version", typeof(uint));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Version", _version);
        }

        public HelloEventArgs(uint version)
        {
            _version = version;
        }

        public uint Version
        {
            get { return _version; }
        }
    }

    [Serializable()]
    public class StatusEventArgs : EventArgs, ISerializable
    {
        private readonly KegBotStatus _oldStatus;
        private readonly KegBotStatus _newStatus;

        public StatusEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this._oldStatus = (KegBotStatus)info.GetValue("OldStatus", typeof(KegBotStatus));
            this._newStatus = (KegBotStatus)info.GetValue("NewStatus", typeof(KegBotStatus));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("OldStatus", _oldStatus);
            info.AddValue("NewStatus", _newStatus);
        }

        public StatusEventArgs(KegBotStatus oldStatus, KegBotStatus newStatus)
        {
            _oldStatus = oldStatus;
            _newStatus = newStatus;
        }

        public KegBotStatus OldStatus
        {
            get { return _oldStatus; }
        }

        public KegBotStatus NewStatus
        {
            get { return _newStatus; }
        }

    }

    [Serializable()]
    public class PacketEventArgs : EventArgs, ISerializable
    {
        private readonly byte[] packetBytes;
        private readonly PacketType type;

        public PacketEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this.packetBytes = (byte[])info.GetValue("Packet", typeof(byte[]));
            this.type = (PacketType)info.GetValue("Type", typeof(PacketType));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Packet", packetBytes);
            info.AddValue("Type", type);
        }

        public PacketEventArgs(byte[] array, PacketType packettype)
        {
            // Not sure this does what I intend
            packetBytes = array;
            type = packettype;
        }

        public byte[] Packet
        {
            get { return packetBytes; }
        }

        public PacketType Type
        {
            get { return type; }
        }
    }

    [Serializable()]
    public class PourEventArgs : EventArgs, ISerializable
    {
        private readonly double volume;
        private readonly byte tap;
        private readonly DateTime time;

        public PourEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this.tap = (byte)info.GetValue("Tap", typeof(byte));
            this.time = (DateTime)info.GetValue("Time", typeof(DateTime));
            this.volume = (double)info.GetValue("Volume", typeof(double));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Tap", Tap);
            info.AddValue("Time", Time);
            info.AddValue("Volume", Volume);
        }

        public PourEventArgs(byte tap, double volume, DateTime time)
        {
            this.tap = tap;
            this.time = time;
            this.volume = volume;
        }

        public double Volume
        {
            get { return volume; }
        }

        public byte Tap
        {
            get { return tap; }
        }

        public DateTime Time
        {
            get { return time; }
        }
    }

    [Serializable()]
    public class TemperatureEventArgs : EventArgs, ISerializable
    {
        private readonly double temperature;
        private readonly string address;
        private readonly DateTime time;

        public TemperatureEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this.address = (string)info.GetValue("Address", typeof(string));
            this.time = (DateTime)info.GetValue("Time", typeof(DateTime));
            this.temperature = (double)info.GetValue("Temperature", typeof(double));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Address", Address);
            info.AddValue("Time", Time);
            info.AddValue("Temperature", Temperature);
        }

        public TemperatureEventArgs(string address, double temperature, DateTime time)
        {
            this.address = address;
            this.time = time;
            this.temperature = temperature;
        }

        public double Temperature
        {
            get { return temperature; }
        }

        public string Address
        {
            get { return address; }
        }

        public DateTime Time
        {
            get { return time; }
        }
    }

    [Serializable()]
    public class UserAuthenticatedEventArgs : EventArgs, ISerializable
    {
        private readonly int id;

        public UserAuthenticatedEventArgs(SerializationInfo info, StreamingContext ctxt)
        {
            this.id = (int)info.GetValue("Id", typeof(int));
        }

        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Id", id);
        }

        public UserAuthenticatedEventArgs(int id)
        {
            this.id = id;
        }

        public int Id
        {
            get { return id; }
        }
    }
}
